// track_silhouette.cpp : main project file.

#include "stdafx.h"
#include <cv.h>
#include "cvaux.h"
#include <cxcore.h>
#include <highgui.h>
#include <stdio.h>

using namespace System;


int main(int argc, char** argv)
{
    IplImage*       cap_frame = NULL;
	IplImage*       im_morphed = NULL;
    CvCapture*      cap = NULL;

    // Initialize capture from camera
	cap = cvCaptureFromCAM(0);

	// Capture initial frame, to check if cam is working
    cap_frame = cvQueryFrame(cap);
    if(!cap_frame)
    {
        printf("bad video \n");
        exit(0);
    }

	

	// Initialize parameters of FG-BG separation
	CvFGDStatModelParams params = {CV_BGFG_FGD_LC, CV_BGFG_FGD_N1C, CV_BGFG_FGD_N2C, CV_BGFG_FGD_LCC,
                                CV_BGFG_FGD_N1CC, CV_BGFG_FGD_N2CC, 1, 0, CV_BGFG_FGD_ALPHA_1, CV_BGFG_FGD_ALPHA_2,
                                CV_BGFG_FGD_ALPHA_3, CV_BGFG_FGD_DELTA, CV_BGFG_FGD_T, CV_BGFG_FGD_MINAREA};


	params.minArea = 50;
	params.is_obj_without_holes = 1;
	params.alpha2 = 0.0001f;

	// Create model
	CvBGStatModel* bg_model = cvCreateFGDStatModel( cap_frame, &params);

    // Create windows (mostly for debug use...
	cvNamedWindow("BG", 1);
    cvNamedWindow("FG", 1);
	cvNamedWindow("MORPH", 1);

	// Initialize further image buffers
	im_morphed = cvCloneImage(bg_model->foreground);

	// Initialize structuring element for morphological operations
	int n = 2;
	IplConvKernel* seSmallNoise = cvCreateStructuringElementEx( n*2+1, n*2+1, n, n, CV_SHAPE_ELLIPSE, 0 );
	n = 10;
	IplConvKernel* seConnect = cvCreateStructuringElementEx( n*2+1, n*2+1, n, n, CV_SHAPE_ELLIPSE, 0 );
	n = 10;
	IplConvKernel* seLarge = cvCreateStructuringElementEx( n*2+1, n*2+1, n, n, CV_SHAPE_ELLIPSE, 0 );
    

    // Run capture loop
	
    for( int fr = 1;cap_frame; cap_frame = cvQueryFrame(cap), fr++ )
    {
        // Update model (i.e. feed latest capture into the model
		cvUpdateBGStatModel( cap_frame, bg_model );
        cvShowImage("BG", bg_model->background);
		
		// Ensure origin is the same with both images (prevents images from being flipped
		bg_model->foreground->origin = bg_model->background->origin;
        cvShowImage("FG", bg_model->foreground);

		// Perform OpenClose
		
		// Remove small noise
		cvErode(bg_model->foreground,im_morphed,seSmallNoise,1);

		// Connect blops
        cvDilate(im_morphed,im_morphed,seConnect,1);
		
		// Take only really large blobs (i.e. person)
		//cvErode(im_morphed,im_morphed,seLarge,1);

		// Show
		im_morphed->origin = bg_model->background->origin;
		cvShowImage("MORPH", im_morphed);

		// Wait some time till next capture
        char k = cvWaitKey(5);
        if( k == 27 ) break;
    }

	// Clean up
	cvReleaseStructuringElement(&seLarge);
	cvReleaseStructuringElement(&seSmallNoise);
	cvReleaseStructuringElement(&seConnect);
    cvReleaseBGStatModel( &bg_model );
	// responsible for some sort of crash at the end: cvReleaseImage(&cap_frame);
    cvReleaseCapture(&cap);
	
	cvReleaseImage(&im_morphed);
	

    return 0;
}

